/*
**    Copyright (C) 2003-2011 Institute for Systems Biology
**                            Seattle, Washington, USA.
**
**    This library is free software; you can redistribute it and/or
**    modify it under the terms of the GNU Lesser General Public
**    License as published by the Free Software Foundation; either
**    version 3 of the License, or (at your option) any later version.
**
**    This library is distributed in the hope that it will be useful,
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
**    Lesser General Public License for more details.
**
**    You should have received a copy of the GNU Lesser General Public
**    License along with this library; if not, write to the Free Software
**    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
*/

package org.systemsbiology.iteration;

import java.util.Iterator;

/**
 * An Iterable that takes a sequence of Iterable and iterates
 * over each Iterator in sequence, only failing a HasNext() check
 * once all Iterators are exhausted.
 * 
 * @author anorberg
 *
 * @param <T> Yield type of the iterators.
 */
public class CompoundIterable<T> implements Iterable<T> {

	private Iterable<? extends Iterable<? extends T>> backing;
	
	/**
	 * Constructs a CompoundIterable that is reusable if all backing Iterables are.
	 * @param collection Iterable of iterables to produce a compound iteration over. Stored by reference,
	 *        so changes to this collection could cause trouble (possible ConcurrentModificationExceptions
	 *        due to checks in underlying iterators, but these are never guaranteed, so they're
	 *        debugging-only).
	 */
	public CompoundIterable(Iterable<? extends Iterable<? extends T>> collection){
		backing = collection;
	}
	
	@Override
	public Iterator<T> iterator() {
		//the following incredibly stupid code is courtesy of Java generic contravariance behavior
		return new CompoundIterator<T>(
				new IteratorConverter<Iterable<? extends T>, Iterator<T>>(backing.iterator()){
					protected Iterator<T> convert(Iterable<? extends T> next) {
						return new IteratorConverter<T, T>(next.iterator()){
							protected T convert(T next) {
								return next;
							}
							
						};
					}
					
				});
	}

}
